-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[Wasm RyuJit] Control flow codegen #121973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Wasm RyuJit] Control flow codegen #121973
Conversation
Emit plausible Wasm control flow for blocks during `genCodeForBBList`. Also add a bit of support for relop codegen, so blocks ending in branches have something to use. Contributes to dotnet#121178.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements WebAssembly control flow code generation during the genCodeForBBList phase, enabling the JIT to emit structured control flow for Wasm blocks, loops, and branches. The implementation includes basic relational operator (relop) support for conditional branches.
Key changes include:
- Addition of Wasm control flow and relational operation instructions to the instruction table
- Movement of
WasmIntervalclass fromfgwasm.cpptofgwasm.hfor use during code generation - Integration of the Wasm control flow transformation phases into the compilation pipeline (non-DEBUG builds)
- Implementation of control flow instruction emission in
genCodeForBBlist, including block/loop/end nesting and branch depth calculation - Basic GT_GT (greater than) relational operator codegen support
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| instrswasm.h | Adds Wasm control flow instructions (block, loop, if, else, end, br, br_if, br_table, return) and relational operators (eqz, eq, ne, lt, gt, le, ge for i32, i64, f32, f64 types) |
| fgwasm.h | Moves WasmInterval class definition from .cpp to header for codegen access |
| fgwasm.cpp | Moves WasmInterval to header, adds block reordering with branch condition reversal, adds debug dump functions, removes debug-only control flow simulation code |
| jitconfigvalues.h | Removes JitWasmControlFlow debug config option (now enabled for TARGET_WASM) |
| compiler.h | Adds WasmInterval forward declaration and fgWasmIntervals field to store control flow intervals for codegen |
| compiler.cpp | Moves Wasm SCC transformation and control flow phases from DEBUG-only to TARGET_WASM builds, repositions them in compilation pipeline |
| lowerwasm.cpp | Implements LowerJTrue to defer branch handling to codegen instead of using NYI |
| emitwasm.h | Adds code_t typedef for instruction opcodes |
| emitwasm.cpp | Implements insOpcode lookup, emitOutputInstr for IF_OPCODE/IF_ULEB128 formats, emitJumpKindToIns mapping, placeholder getInsExecutionCharacteristics |
| emitjmps.h | Defines Wasm jump kinds: br, br_if, br_table |
| codegenwasm.cpp | Implements genFnProlog, adds GT_GT to tree node codegen, implements inst_JMP/inst_LABEL for Wasm depth-based branching |
| codegen.h | Adds Wasm-specific inst_JMP and inst_LABEL declarations taking depth parameter |
| codegenlinear.cpp | Adds Wasm control flow stack management, emits block/loop/end instructions around blocks, generates Wasm branches (br, br_if, br_table) at block ends with depth calculation |
| CMakeLists.txt | Moves fgwasm.cpp from common JIT sources to TARGET_WASM-specific sources |
|
FYI @dotnet/jit-contrib @SingleAccretion This won't get much testing in CI... locally it lets us get a simple method like int Foo(int a, int b)
{
if (a > b) return b;
return a;
}through more of codegen. Prolog gen stubbed out for now. Also addresses a few bits of @jakobbotsch's feedback on #121728. The SCC phase is moved later, some debug only stuff is now really debug only, etc. |
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
|
@SingleAccretion think I got most of your feedback, except leaving LABEL as is for now. Wasn't sure what you were commenting on for the prolog. Please take another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for addressing the feedback, it looks much nicer now! I've left a few comments.
|
@SingleAccretion thanks again, pushed another update |
SingleAccretion
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo the genFnProlog comment (#121973 (comment)) and one suggestion.
|
@dotnet/jit-contrib ping |
|
@jakobbotsch now using a common |
jakobbotsch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me now.
adamperlin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me! I don't have any notes I wanted to add at the moment!
#122171) HostActivation tests are hitting the 5-minute hang dump timeout on OSX CI despite making steady progress. Tests complete in ~2 minutes locally but CI environments run 2x slower. **Changes:** - Increased `--hangdump-timeout` from `5m` to `8m` in `src/installer/tests/Directory.Build.props` This provides adequate headroom for slower CI machines while still catching actual hangs. <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Host Activation test failures on OSX</issue_title> > <issue_description>## Build Information > Build: https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=1219628 > Build error leg or test failing: HostActivation.Tests.WorkItemExecution > Pull request: #121973 > <!-- Error message template --> > ## Error Message > > Fill the error message using [step by step known issues guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md). > > <!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern for regex matches (single line/no backtracking). Set BuildRetry to `true` to retry builds with this error. Set ExcludeConsoleLog to `true` to skip helix logs analysis. --> > > ```json > { > "ErrorMessage": "Hang dump timeout of '00:05:00' expired", > "ErrorPattern": "", > "BuildRetry": false, > "ExcludeConsoleLog": false > } > ``` > > > <!-- Known issue validation start --> > ### Known issue validation > **Build: :mag_right:** https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628 > **Error message validated:** `[Hang dump timeout of '00:05:00' expired`] > **Result validation:** :white_check_mark: Known issue matched with the provided build. > **Validation performed at:** 12/4/2025 3:07:33 AM UTC > <!-- Known issue validation end --> > <!--Known issue error report start --> > > ### Report > > |Build|Definition|Test|Pull Request| > |---|---|---|---| > |[1219965](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219965&view=ms.vss-test-web.build-test-results-tab&runId=33790538&resultId=100095)|dotnet/runtime#122136| > |[1219914](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219914&view=ms.vss-test-web.build-test-results-tab&runId=33788030&resultId=100095)|dotnet/runtime#117148| > |[1219763](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219763&view=ms.vss-test-web.build-test-results-tab&runId=33785738&resultId=100095)|dotnet/runtime#122125| > |[1219716](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219716&view=ms.vss-test-web.build-test-results-tab&runId=33780760&resultId=100095)|dotnet/runtime#122168| > |[1219709](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219709&view=ms.vss-test-web.build-test-results-tab&runId=33780492&resultId=100095)|dotnet/runtime#122163| > |[1219628](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628)|dotnet/runtime|[HostActivation.Tests.WorkItemExecution](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1219628&view=ms.vss-test-web.build-test-results-tab&runId=33778378&resultId=100095)|dotnet/runtime#121973| > #### Summary > |24-Hour Hit Count|7-Day Hit Count|1-Month Count| > |---|---|---| > |6|6|6| > <!--Known issue error report end --></issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > <comment_new><author>@agocke</author><body> > My PR almost certainly broke this, but I'm not sure how yet</body></comment_new> > <comment_new><author>@agocke</author><body> > Actually, I'm not sure I "broke" this in a real sense -- right now the hang dump timeout is kicking in at the 5m mark. But the log shows a steady stream of tests passing all the way up to the 5m mark. > > I wonder if this is just that the tests are taking longer than 5m to finish and the hang dump timeout is measuring from the start of the test run.</body></comment_new> > <comment_new><author>@agocke</author><body> > Yeah my uncontended M2 Mac takes 2 min to run the tests, I could easily believe CI is twice as slow. I think we should bump this to ten minutes.</body></comment_new> > </comments> > </details> - Fixes #122169 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: agocke <[email protected]>
This is the first prototype of a Wasm object writer for crossgen that *only* writes out method bodies. It builds the minimum module structure which is needed to declare and export the module bodies so that the resulting module can be loaded and method bodies can be called by an external loader. I have tested the output with a simple JavaScript loader that instantiates the module and calls one of the exports. # What IS handled Emitting simple method bodies from an assembly that have no relocations or external dependencies of any kind. # What is NOT handled ## Relocations and any metadata attached to compiled methods. ## R2R format envelope (the plan is to embed this in the data section in a future PR) R2R metadata is currently unused. ## Signature generation to meet ABI requirements Right now, there is a single `i32 -> i32` signature which is used as a placeholder for any method. Later work will need to build support for generating and storing wasm-level type signatures for JIT compiled methods. ## JIT Integration Currently, the JIT is not called (I believe it will hit asserts on the Wasm target until #121973 is in). Instead, a simple `(i32.const 0) (return)` stub is emitted for any JIT calls. --------- Co-authored-by: Adeel Mujahid <[email protected]> Co-authored-by: Copilot <[email protected]>


Emit plausible Wasm control flow for blocks during
genCodeForBBList.Also add a bit of support for relop codegen, so blocks ending in branches have something to use.
Contributes to #121178.